/**
 * Copyright 2008-2009 HAN.BIFANG
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 */
package han.bashe.common.bifang;

import han.bashe.common.config.Config;
import han.bashe.common.exception.BasheErrorCode;
import han.bashe.common.exception.BasheException;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.RequestEntity;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.apache.commons.httpclient.params.HttpClientParams;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import v1.query.web.bifang.han.QueryRequestDocument;
import v1.query.web.bifang.han.QueryResponseDocument;
import v1.query.web.bifang.han.QueryResponseDocument.QueryResponse;
import v1.query.web.bifang.han.ServiceBusDocument.ServiceBus;
import v1.query.web.bifang.han.ServiceCatDocument.ServiceCat;
import v1.security.web.bifang.han.SecurityRequestDocument;
import v1.security.web.bifang.han.SecurityResponseDocument;
import v1.security.web.bifang.han.AuthenticateRequestDocument.AuthenticateRequest.UserPassword;

/**
 * @Author Kent
 */
public class BifangClient {

	private static Log log = LogFactory.getLog(BifangClient.class);
	private static QueryResponseDocument query(QueryRequestDocument req)
			throws BasheException {
		try {
			log.info("query request is " + req.toString());
			HttpClient httpclient = new HttpClient();
			PostMethod post = new PostMethod(Config.getConfig().getCatalog()
					.getQueryUrl());

			HttpClientParams params = new HttpClientParams();
			params.setSoTimeout(Config.DEFAULT_BIFANG_TIMEOUT * 1000);
			httpclient.setParams(params);

			RequestEntity entity = new StringRequestEntity(req.toString(),
					"text/xml", "UTF-8");
			post.setRequestEntity(entity);

			int result = httpclient.executeMethod(post);

			if (result != 200) {
				throw new BasheException(BasheErrorCode.ACCESS_BIFANG_ERROR,
						"Bifang returns HTTP code " + result);
			}
			String res = post.getResponseBodyAsString();
			log.info("query response is " + res);
			QueryResponseDocument ret = QueryResponseDocument.Factory
					.parse(res);
			if (!ret.validate()) {
				Log log = LogFactory.getLog(BifangClient.class);
				log.error("Bifang return invalid format query response xml");
				log.error(res);
				throw new BasheException(BasheErrorCode.ACCESS_BIFANG_ERROR,
						"Bifang response xml format error");
			}
			if(ret.getQueryResponse().getError() != null){
				throw new BasheException(BasheErrorCode.ACCESS_BIFANG_ERROR,"Bifang return error :"
						+ ret.getQueryResponse().getError());
			}
			return ret;
		} catch (Exception e) {
			if (e instanceof BasheException) {
				throw (BasheException) e;
			}
//			Log log = LogFactory.getLog(BifangClient.class);
//			log.error("query Bifang error", e);
			throw new BasheException(BasheErrorCode.ACCESS_BIFANG_ERROR,
					"query Bifang error", e);

		}

	}

	public static SecurityResponseDocument securityCheck(SecurityRequestDocument req)
			throws BasheException {
		try {
			HttpClient httpclient = new HttpClient();
			PostMethod post = new PostMethod(Config.getConfig().getCatalog()
					.getSecurityUrl());

			HttpClientParams params = new HttpClientParams();
			params.setSoTimeout(Config.DEFAULT_BIFANG_TIMEOUT * 1000);
			httpclient.setParams(params);

			RequestEntity entity = new StringRequestEntity(req.toString(),
					"text/xml", "UTF-8");
			post.setRequestEntity(entity);

			int result = httpclient.executeMethod(post);

			if (result != 200) {
				throw new BasheException(BasheErrorCode.ACCESS_BIFANG_ERROR,
						"Bifang returns HTTP code " + result);
			}
			String res = post.getResponseBodyAsString();
			SecurityResponseDocument ret = SecurityResponseDocument.Factory
					.parse(res);
			if (!ret.validate()) {
				Log log = LogFactory.getLog(BifangClient.class);
				log.error("Bifang return invalid format security response xml");
				log.error(res);
				throw new BasheException(BasheErrorCode.ACCESS_BIFANG_ERROR,
						"Bifang response xml format error");
			}
			
			if(ret.getSecurityResponse().getError() != null){
				throw new BasheException(BasheErrorCode.ACCESS_BIFANG_ERROR,"Bifang return error :"
						+ ret.getSecurityResponse().getError());
			}
			return ret;
		} catch (Exception e) {
			if (e instanceof BasheException) {
				throw (BasheException) e;
			}
//			Log log = LogFactory.getLog(BifangClient.class);
//			log.error("query Bifang error", e);
			throw new BasheException(BasheErrorCode.ACCESS_BIFANG_ERROR,
					"security check error", e);

		}

	}
	
	public static QueryResponse getServiceInfo(String code)throws BasheException{
		QueryRequestDocument doc = QueryRequestDocument.Factory.newInstance();
		doc.addNewQueryRequest().addNewService().setServiceCode(code);
		return query(doc).getQueryResponse();
	}
	
	public static boolean canAccess(String user, String password, String service)throws BasheException{
		SecurityRequestDocument doc = SecurityRequestDocument.Factory.newInstance();
		doc.addNewSecurityRequest().setServiceCode(service);
		UserPassword up = doc.getSecurityRequest().addNewAuthenticateRequest().addNewUserPassword();
		up.setPassword(password);
		up.setUser(user);
		
		SecurityResponseDocument res = securityCheck(doc);
		return res.getSecurityResponse().getResult();
	}
	
	public static ServiceBus getServiceBusInfoByCode(String code)throws BasheException{
		QueryRequestDocument doc = QueryRequestDocument.Factory.newInstance();
		doc.addNewQueryRequest().addNewBus().setBusCode(code);
		return query(doc).getQueryResponse().getResult().getServiceBus();
	}
	
	public static ServiceBus getServiceBusInfoById(String id)throws BasheException{
		QueryRequestDocument doc = QueryRequestDocument.Factory.newInstance();
		doc.addNewQueryRequest().addNewBus().setBusId(id);
		return query(doc).getQueryResponse().getResult().getServiceBus();
	}
	
	public static ServiceCat getDefaultServiceCatalog()throws BasheException{
		QueryRequestDocument doc = QueryRequestDocument.Factory.newInstance();
		doc.addNewQueryRequest().setCatalog(" ");
		return query(doc).getQueryResponse().getResult().getServiceCat();
	}
	
	
}
